#include <assert.h>
#include <iostream>

#include "SpawnTests.hpp"
#include "../Spawn.hpp"

#ifdef WIN32
#include <windows.h>
#endif

namespace EGlib
{
  static Glib::ustring get_testproc_file_name()
  {
#ifdef WIN32
    wchar_t cur_exe_wide[MAX_PATH];
    DWORD res = GetModuleFileNameW(GetModuleHandle(0),cur_exe_wide,sizeof(cur_exe_wide) / sizeof(cur_exe_wide[0]));
    assert(res != 0);

    gchar *cur_exe_str = g_utf16_to_utf8((gunichar2*)cur_exe_wide,-1,0,0,0);
    assert(cur_exe_str);
    Glib::ustring cur_exe = cur_exe_str;
    g_free(cur_exe_str);

    Glib::ustring ret = Glib::path_get_dirname(cur_exe) + "\\TestProc.exe";
    return ret;
    
#else
    return "TestProc";
#endif
  }

  void SpawnTests::test_cmdline_args()
  {
    Glib::ustring testproc_file_name = get_testproc_file_name();
    Process proc(testproc_file_name);

    proc.add_argument("-test-cmdline-args");
    proc.add_argument("c:\\windows\\\"file name\".txt");
    proc.add_argument("   ");

    int ret = proc.spawn_sync();
    assert(ret == 0);
  }

  void SpawnTests::test_piping()
  {
    /*Process proc("TestProc");
    proc.add_argument("-test_piping");
    
    proc.spawn_sync();*/
  }

  void SpawnTests::test_proc_return_val()
  {
    Glib::ustring testproc_file_name = get_testproc_file_name();

    {
      Process proc(testproc_file_name);
      proc.add_argument("-r0");
      assert(proc.spawn_sync() == 0);
    }
    
    {
      Process proc(testproc_file_name);
      proc.add_argument("-r1");
      assert(proc.spawn_sync() == 1);
    }
    
    {
      Process proc(testproc_file_name);
      proc.add_argument("-r123");
      assert(proc.spawn_sync() == 123);
    }
    
    {
      Process proc(testproc_file_name);
      proc.add_argument("-r-5");
      assert(proc.spawn_sync() == -5);
    }

  }

  void SpawnTests::test_non_existing_executable()
  {
    try
    {
      Process proc("non_existing");
      
      proc.spawn_sync();
      
      assert(!"an exception should have been thrown");
    }
    catch(const Glib::Exception&)
    {
      // this block is the expected behaviour.
    }
  }
}

